<?php
require_once 'config.php';

define('DEBUG', true);
define('PATH_TO_DB_INIT', RESOURCE_DIR . '/schema.sql');

require_once '../sys/mublog.php';

class InstallEnvironment extends BaseMublogEnvironment {
    public function getRoutes() {
        return array(
            '/' => 'welcome',
            '/1' => 'install.step1',
            '/2' => 'install.step2'
        );
    }
    
    public function getRouteMapping() {
        return array(
            'welcome' => 'welcomeController',
            'install.step1' => 'installController->step1',
            'install.step2' => 'installController->step2'
        );
    }
    
    public function getInstallController() {
        $controller = new InstallController();
        $controller->setDatabase($this->database);
        $this->initMublogController($controller);
        
        return $controller;
    }
    
    public function getWelcomeController() {
        $controller = new WelcomeController();
        $this->initController($controller);
        
        return $controller;
    }
}

class WelcomeController extends Controller {
    public function do_GET(Request $request) {
        $checks = array(
            new ClosureConfigCheck(_('Data directory is writeable'),
                    function () {
                        return is_writable(DATA_DIR);
                    })
        );
        
        return $this->render('install/welcome', $request, array(
            'checks' => $checks,
            'globalCheck' => new GlobalConfigCheck($checks)
        ));
    }
}

class InstallController extends MublogController {
    private $database;
    
    /**
     * @var BlogSettings
     */
    private $blogSettings;
    
    /**
     * @var BlogSettingsForm
     */
    private $blogSettingsForm;
    
    /**
     * @var MublogUserForm
     */
    private $userForm;
    
    public function do_step1_GET(Request $request) {
        $this->getDatabase()->initWithFile(PATH_TO_DB_INIT);
        
        return $this->render('install/blog-settings', $request, array(
            'blogSettings' => $this->getBlogSettings(),
            'form' => $this->getBlogSettingsForm()
        ));
    }
    
    public function do_step1_POST(Request $request) {
        $blogSettings = $this->getBlogSettings();
        $form = $this->getBlogSettingsForm();
        $form->parseInto($blogSettings, $request);
        
        if ($form->validate($blogSettings)) {
            $this->getBlogSettingsManager()->updateBlogSettings($blogSettings);
            return $this->redirect('install.step2');
        }
        else {
            return $this->do_step1_GET($request);
        }
    }
    
    public function do_step2_GET(Request $request) {
        return $this->render('install/create-user', $request, array(
            'form' => $this->getUserForm(),
            'user' => new User()
        ));
    }
    
    public function do_step2_POST(Request $request) {
        $user = new User();
        $form = $this->getUserForm();
        $form->parseInto($user, $request);
        
        if ($form->validate($user)) {
            $this->getAuthenticator()->createUser($user);
            return $this->redirect('install.step3');
        }
        else {
            return $this->do_step2_GET($request);
        }
    }
    
    public function getBlogSettings() {
        if ($this->blogSettings === null) {
            $this->blogSettings = $this->getBlogSettingsManager()
                    ->getBlogSettings();
        }
        
        return $this->blogSettings;
    }
    
    /**
     * @return BlogSettingsForm
     */
    private function getBlogSettingsForm() {
        if ($this->blogSettingsForm === null) {
            $this->blogSettingsForm = new BlogSettingsForm('blogSettings');
        }
        
        return $this->blogSettingsForm;
    }
    
    /**
     * @return MublogUserForm
     */
    private function getUserForm() {
        if ($this->userForm === null) {
            $this->userForm = new MublogUserForm();
        }
        
        return $this->userForm;
    }
    
    public function getDatabase() {
        return $this->database;
    }

    public function setDatabase($database) {
        $this->database = $database;
    }
}

interface ConfigCheck {
    function isOk();
    function getText();
}

class ClosureConfigCheck implements ConfigCheck {
    private $closure;
    private $text;
    private $ok = null;
    
    public function __construct($text, $closure) {
        $this->text = $text;
        $this->closure = $closure;
    }
    
    public function isOk() {
        if ($this->ok === null) {
            $this->ok = call_user_func($this->closure);
        }
        
        return $this->ok;
    }
    
    public function getText() {
        return $this->text;
    }
}

class GlobalConfigCheck implements ConfigCheck {
    private $checks;
    
    public function __construct(array $checks) {
        $this->checks = $checks;
    }
    
    public function getText() {
        return "Global";
    }
    
    public function isOk() {
        foreach ($this->checks as $check) {
            if (!$check->isOk()) {
                return false;
            }
        }
        
        return true;
    }
}

class BlogSettingsForm extends AbstractForm {
    protected function init() {
        $this
            ->add('name', _('Name'), _('The name of your blog'))
            ->add('mission', _('Mission'),
                _('The mission statement briefly describes your blog'));
    }
    
    public function validate(BlogSettings $settings) {
        return $this->validateProperties($settings, 'name', 'mission');
    }
}

$app = new Application(new InstallEnvironment());
$app->run();
